import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:my_desk_flutter/api/bus_api.dart';
import 'package:my_desk_flutter/di/custom_di.dart';
import 'package:my_desk_flutter/page/home_page.dart';
import 'package:my_desk_flutter/routes/app_router.dart';
import 'package:my_desk_flutter/storage/local_file_provider.dart';
import 'package:path_provider/path_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:http/http.dart' as http;

import 'storage/hive_storage_service.dart';
import 'storage/storage_service.dart';
import 'storage/storage_service_provider.dart';

part 'main.g.dart';

Future main() async {
  runZonedGuarded(() async {
    await Hive.initFlutter();
    final StorageService initializedStorageService = HiveStorageService();
    final tempDir = await getTemporaryDirectory();
    await initializedStorageService.init();
    await ScreenUtil.ensureScreenSize();
    configureDependencies();
    runApp(
      ProviderScope(
        overrides: [
          storageServiceProvider.overrideWithValue(initializedStorageService),
          localFileProvider.overrideWithValue(tempDir),
        ],
        child: const MyApp(),
      ),
    );
  }, (error, stack) {});
  // Add this line
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    ScreenUtil.init(context);
    // ;
    return MaterialApp(
      title: 'Flutter Demo',
      onGenerateRoute: (RouteSettings settings) {
        return AppRouter.router[settings.name]?.call(settings.arguments) ??
            MaterialPageRoute(
              builder: (ctx) {
                return Material(
                  child: Center(
                    child: Text("path:${settings.name} NOT FOUND!"),
                  ),
                );
              },
            );
      },
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightGreen),
        useMaterial3: true,
        textTheme: TextTheme(
          titleLarge: TextStyle(
            fontSize: 20.sp,
            color: const Color(0xff333333),
          ),
          titleMedium: TextStyle(
            fontSize: 16.sp,
            color: const Color(0xff333333),
          ),
          titleSmall: TextStyle(
            fontSize: 12.sp,
            color: const Color(0xff333333),
          ),
          labelMedium: TextStyle(
            fontSize: 16.sp,
            color: const Color(0xff333333),
          ),
          labelSmall: TextStyle(
            fontSize: 12.sp,
            color: const Color(0xFF858A8C),
          ),
        ),
      ),
      initialRoute: '/',
    );
  }
}

@riverpod
String example(ExampleRef ref) {
  return 'foo';
}

final activityProvider = FutureProvider.autoDispose((ref) async {
  await Future.delayed(const Duration(milliseconds: 1000 * 5));
  return {};
  // 使用 package:http, 我们可以从 Bored API 获取一个随机的活动。
  final response = await http.get(Uri.https('boredapi.com', '/api/activity'));
  // 使用 dart:convert, 然后我们将 JSON 有效负载解码为 Map 数据结构。
  final json = jsonDecode(response.body) as Map<String, dynamic>;
  // 最后，我们将 Map 转换为 Activity 实例。
  return json;
});

final helloWorldProvider = StateProvider((ref) {
  return 0;
});
int n = 0;
final testAutoDisposed =
    FutureProvider.autoDispose.family<String, String>((ref, args) async {
  ref.state = const AsyncLoading();
  await Future.delayed(const Duration(milliseconds: 3 * 1000));
  ref.onDispose(() {
    print("执行了销毁:${n}");
  });
  n++;
  return "这是一个返回值:$args";
});

class Todo {
  Todo({
    required this.description,
    this.completed = false,
  });

  factory Todo.fromJson(Map<String, dynamic> json) {
    return Todo(
      description: json['description'] as String,
      completed: json['completed'] as bool,
    );
  }

  final String description;
  final bool completed;
}

// 因为我们的逻辑是异步的，所以我们需要使用 AsyncNotifier。
// 特别的，由于使用“autoDispose”修饰符，
// 我们需要 AutoDisposeAsyncNotifier。
class TodoList extends AutoDisposeAsyncNotifier<List<Todo>> {
  @override
  Future<List<Todo>> build() async {
    // 我们之前在 FutureProvider 中的业务逻辑现在位于 build 方法中。
    final n = switch (ref.watch(testAutoDisposed('随机2'))) {
      AsyncData(:final value) => value,
      AsyncLoading() => "正在加载",
      AsyncError(:final error) => "产生了错误:$error",
      _ => "",
    };
    print("------------->");
    return [
      Todo(description: 'Learn Flutter counter : $n', completed: true),
      Todo(description: 'Learn Riverpod'),
    ];
  }

  Future<void> addTodo(Todo todo) async {
    // ref.watch(helloWorldProvider);
    await Future.delayed(const Duration(milliseconds: 3 * 1000));
    final previousState = await future;
    state = AsyncData([...previousState, todo]);
    // await future;
  }
}

// 我们现在使用 AsyncNotifierProvider 替代 FutureProvider
final todoListProvider =
    AsyncNotifierProvider.autoDispose<TodoList, List<Todo>>(
  TodoList.new,
);

class MyHomePage extends ConsumerWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final int counter = ref.watch(helloWorldProvider);
    // 读取 activityProvider。如果没有准备开始，这将会开始一个网络请求。
    // 通过使用 ref.watch，小组件将会在 activityProvider 更新时重建。
    // 当下面的事情发生时，会更新小组件：
    // - 响应从“正在加载”变为“数据/错误”
    // - 请求重刷新
    // - 结果被本地修改（例如执行副作用时）
    // ...
    final AsyncValue<dynamic> activity = ref.watch(activityProvider);
    final data = ref.watch(todoListProvider);
    return Scaffold(
      appBar: AppBar(title: const Text('Example')),
      floatingActionButton: Row(
        children: [
          FloatingActionButton(
            onPressed: () {
              ref.refresh(testAutoDisposed('随机1'));
              // ref.read(helloWorldProvider);
            },
            child: const Icon(Icons.refresh),
          ),
          FloatingActionButton(
            onPressed: () {
              ref.read(helloWorldProvider.notifier).state += 1;
              // ref.read(helloWorldProvider);
            },
            child: const Icon(Icons.add),
          ),
        ],
      ),
      body: Center(
        child: Column(
          children: [
            Text("$counter"),

            switch (ref.watch(testAutoDisposed('随机1'))) {
              AsyncData(:final value) => Text(value),
              _ => const CircularProgressIndicator(),
            },
            MaterialButton(
              child: const Text("添加一个待办"),
              onPressed: () {
                ref
                    .read(todoListProvider.notifier)
                    .addTodo(Todo(description: '新增了一个待办'));
              },
            ),
            if (data is AsyncData)
              ...data.value!.map((e) => Text("待办:${e.description}")),
            // switch (activity) {
            //   AsyncData(:final value, :final isLoading) =>
            //     Text("${value} ${isLoading}"),
            //   AsyncError() => const Text('Oops, something unexpected happened'),
            //   _ => const CircularProgressIndicator()
            // }
          ],
        ),
      ),
    );
  }
}
